import fetch from "dva/fetch";
import CryptoJS from "crypto-js";
import { notification, message } from "antd";
import router from 'umi/router';
// import Cookies from "js-cookie";
import { getConfig } from "../../config";


const config = getConfig();
const ajaxPrefix = config.ajaxPrefix;
const isMock = config.isMock;
const key = CryptoJS.enc.Utf8.parse(CryptoJS.MD5("panshiyu").toString());
const iv  = CryptoJS.enc.Utf8.parse(CryptoJS.MD5(key).toString().substr(0,16));

// 生成UUID
const generateUUID = (len, radix) => {
  const chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".split(
    ""
  );
  let uuid = [],
    i;
  radix = radix || chars.length;
  if (len) {
    // Compact form
    for (i = 0; i < len; i++) uuid[i] = chars[0 | (Math.random() * radix)];
  } else {
    // rfc4122, version 4 form
    let r;
    // rfc4122 requires these characters
    uuid[8] = uuid[13] = uuid[18] = uuid[23] = "-";
    uuid[14] = "4";
    // Fill in random data.  At i==19 set the high bits of clock sequence as
    // per rfc4122, sec. 4.1.5
    for (i = 0; i < 36; i++) {
      if (!uuid[i]) {
        r = 0 | (Math.random() * 16);
        uuid[i] = chars[i == 19 ? (r & 0x3) | 0x8 : r];
      }
    }
  }
  return uuid.join("");
};

const generateTerminalUid = () => {
  const terminalUid = generateUUID(32);
  // PC端以03_开头
  return `3_${terminalUid}`;
};

//AES加密
export const  encrypt = (data) => {
  let encrypted='';
  if(typeof(data)=='string')
  {
    encrypted = CryptoJS.AES.encrypt(data,key,{
      iv : iv,
      mode : CryptoJS.mode.CBC,
      padding : CryptoJS.pad.ZeroPadding
    });
  }else if(typeof(data)=='object'){
    data = JSON.stringify(data);
    encrypted = CryptoJS.AES.encrypt(data,key,{
      iv : iv,
      mode : CryptoJS.mode.CBC,
      padding : CryptoJS.pad.ZeroPadding
    })
  }
  return encrypted.toString();
}


/*AES解密
* param : message 密文
* return : decrypted string 明文
*/
export const  decrypt = (message) => {
  let decrypted='';
  decrypted=CryptoJS.AES.decrypt(message,key,{
    iv : iv,
    mode : CryptoJS.mode.CBC,
    padding : CryptoJS.pad.ZeroPadding
  });
  return JSON.parse(decrypted.toString(CryptoJS.enc.Utf8));
}

export const terminalUid = generateTerminalUid();

// password 加密
export const generateAuthPassword = password => {
  // return CryptoJS.enc.Hex.stringify(CryptoJS.SHA256(password));
  return password;
};

export const getUserInfo = () => {
  // const userInfo = Cookies.get("__ywweb_user_info");
  const userInfo =sessionStorage.getItem("__ywweb_user_info");
  return (userInfo && decrypt(userInfo)) || {};
};

export const getSiteLogo = () => {
  const defaultHeadpic = require("../assets/img/logo@2x.png");
  return defaultHeadpic;
};

export const getSiteTitle = () => {
  // const defaultTitle =  "奉化施公安局设备运维管理系统";
  const defaultTitle =  "设备运维管理系统";
  return defaultTitle;
};

export const getAccessToken = () => {
  // return Cookies.get("__ywweb_access_token");
  return sessionStorage.getItem("__ywweb_access_token");
};

export const getUserRoles = () => {
  const userRole =sessionStorage.getItem("__ywweb_user_roles");
  // const userRole = Cookies.get("__ywweb_user_roles");
  return (userRole && decrypt(userRole)) || [];
};

const toQueryParam = data => {
  let returnVal;
  for (const key in data) {
    if (typeof returnVal === "undefined") {
      returnVal = "";
    } else {
      returnVal += "&";
    }
    returnVal += key;
    returnVal += "=";
    returnVal += data[key];
  }
  return returnVal;
};




const codeMessage = {
  200: '服务器成功返回请求的数据。',
  201: '新建或修改数据成功。',
  202: '一个请求已经进入后台排队（异步任务）。',
  204: '删除数据成功。',
  400: '发出的请求有错误，服务器没有进行新建或修改数据的操作。',
  401: '用户没有权限（令牌、用户名、密码错误）。',
  403: '用户得到授权，但是访问是被禁止的。',
  404: '发出的请求针对的是不存在的记录，服务器没有进行操作。',
  406: '请求的格式不可得。',
  410: '请求的资源被永久删除，且不会再得到的。',
  422: '当创建一个对象时，发生一个验证错误。',
  // 500: '服务器发生错误，请检查服务器。',
  502: '网关错误。',
  503: '服务不可用，服务器暂时过载或维护。',
  504: '网关超时。',
};

const checkStatus = response => {
  // console.log('response',response)
  if (response.status >= 200 && response.status < 300) {
    return response;
  }
  const errortext = codeMessage[response.status] || response.statusText;

  const error = new Error();
  error.code = response.status;
  error.message = errortext;
  throw error;
};

const errorThrow = (error, url) =>{
  const status = Number(error.code);
  if (status === 401) {
    // @HACK
    /* eslint-disable no-underscore-dangle */
    window.g_app._store.dispatch({
      type: 'login/logout',
    });
    return;
  }
  // environment should not be used
  if (status === 403) {
    router.push('/exception/403');
    return;
  }
  if (status === 404) {
    router.push('/exception/404');
    return;
  }
  // if (status <= 504 && status >= 500) {
  //   router.push('/exception/500');
  //   return;
  // }
  // if (status >= 404 && status < 422) {
  //   router.push('/exception/404');

    // 跳转后弹出错误信息
    if ("stack" in error && "message" in error) {
      if (process.env.NODE_ENV === "development") {
        notification.error({
          message: `请求错误: ${url.split("?")[0]}`,
          description: error.message
        });
      } else {
        notification.error({
          message: `系统提示`,
          description: error.message
        });
        // message.error(error.message);
      }
    }
  // }

}


export const getFetchHeader = () => {
  const accessToken = getAccessToken();
  const defaultOpitonHeader = {
    "token": accessToken,
    // "EQ-TerminalUid": terminalUid
    // 'EQ-TenantId': 200020,
  };
  return defaultOpitonHeader;
};

/**
 * Requests a URL, returning a promise.
 *
 * @param  {string} url       The URL we want to request
 * @param  {object} [options] The options we want to pass to "fetch"
 * @return {object}           An object containing either "data" or "err"
 */

export const request = (url, options, successfun, failfun, fetchtype) => {
  let defaultOptions;
  if (process.env.NODE_ENV === "product") {
    defaultOptions = {};
  } else {
    defaultOptions = {
      // credentials: 'include',
      credentials: "same-origin",
      mode: "cors"
    };
  }
  const newOptions = { ...defaultOptions, ...options };

  const defaultOpitonBody = {
    // accessToken: accessToken,
    // terminal_uid: terminalUid,
  };
  const defaultOpitonHeader = getFetchHeader();

  let fetchurl;
  if(!isMock ){
  // if (process.env.NODE_ENV === "development" &&  !isMock ){
    fetchurl = `${ajaxPrefix}${url}`;
  }else{
    fetchurl = `${url}`;
  }


  if (
    newOptions.method === "POST" ||
    newOptions.method === "PUT" ||
    newOptions.method === "OPTIONS"
  ) {

    newOptions.headers = {
      Accept: "application/json",
      "Content-Type": "application/json; charset=utf-8",
      ...defaultOpitonHeader,
      ...newOptions.headers
    };
    newOptions.body = JSON.stringify({
      ...defaultOpitonBody,
      ...newOptions.body
    });

  }

  // 下载文件的请求走这里
  if (fetchtype === "download") {
    return fetch(fetchurl, newOptions)
      .then(checkStatus)
      .then(response =>
        response.blob().then(blob => {
          const filename = response.headers.get("content-filename")
            ? decodeURI(response.headers.get("content-filename"))
            : "本地下载测试";
          const ErrorInfo =
            response.headers.get("Content-Errorinfo") &&
            decodeURI(response.headers.get("Content-Errorinfo"));
          if (ErrorInfo) {
            message.error(ErrorInfo);
          } else {
            if('msSaveOrOpenBlob' in navigator){
              window.navigator.msSaveOrOpenBlob(new Blob([data]), filename);
            }else{
              const a = document.createElement("a");
              const url = window.URL.createObjectURL(blob); // 获取 blob 本地文件连接 (blob 为纯二进制对象，不能够直接保存到磁盘上)
              a.href = url;
              a.download = filename;
              a.click();
              window.URL.revokeObjectURL(url);
            }

          }
        })
      )
      .catch(error => {
        errorThrow(error,fetchurl);
      });
  } else {
    return new Promise((resolve, reject) => {
      fetch(fetchurl, newOptions, successfun, failfun)
        .then(checkStatus)
        .then(response => response.json())
        .then(data => {
          // 接口调用成功
          // alert(url+"|"+JSON.stringify(data));
          const errorNo = data.error_no;
          // 接口抛错
          if (typeof errorNo !== "undefined" && errorNo != "0") {
            const error = new Error();
            error.code = data.error_no;
            error.message = codeMessage[Number(data.error_no)] || data.error_info;
            error.data = data.data;
            throw error;
          }

          // 接口返回预期数据
          if (typeof successfun === "function") {
            return successfun.bind(this)(data);
          }

          return data;
        })
        .then(json => {
          resolve(json);
        })
        .catch(error => {
          // 需要特殊处理的接口编号
          if (failfun instanceof Array && failfun.indexOf(error.code) !== -1) {
            return error;
          }

          // 接口抛错统一处理
          errorThrow(error,fetchurl);

          // console.log('rej',error)
          // rej('失败了')
          Promise.reject('出错了');
          return false;
          // throw error;
          // return Promise.reject(error);
        });
    });
  }
};
